﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.Reflection;
using AutoMapper;
using Oracle.DataAccess.Client;

namespace Wicresoft.UnifyShow.BusinessImpl
{
    class AutoMapper
    {
        private static Dictionary<string, PropertyInfo[]> _maps = new Dictionary<string, PropertyInfo[]>();
        public static List<M> Map<T, M>(T reader, IList<string> listColumns = null) where T : IDataReader
        {
            List<M> listM = new List<M>();
            Type type = typeof(M);

            List<string> dbColumns = new List<string>();
            for (int i = 0; i < reader.FieldCount; i++)
                dbColumns.Add(reader.GetName(i));

            var properties = GetPropertyInfos(type).Where(o => dbColumns.Contains(o.Name, StringComparer.InvariantCultureIgnoreCase));

            if (listColumns != null) properties = properties.Where(o => listColumns.Contains(o.Name, StringComparer.InvariantCultureIgnoreCase));

            M model;
            Object oTemp;
            while (reader.Read())
            {
                model = Activator.CreateInstance<M>();
                foreach (var item in properties)
                {
                    //try
                    //{
                    oTemp = reader[item.Name];
                    if (oTemp is DBNull) continue;
                    item.SetValue(model, oTemp, null);
                    //}
                    //catch (ArgumentException e) { }
                    // catch (IndexOutOfRangeException e1) { }
                }
                listM.Add(model);
            }
            return listM;
        }
        public static IList<QueryParameter> GenerateUpdateSome<M>(M model, IList<string> exceptString)
        {
            Type type = typeof(M);
            PropertyInfo[] properties = GetPropertyInfos(type).Where(o => !exceptString.Contains(o.Name)).ToArray();
            IList<QueryParameter> result = new List<QueryParameter>();
            QueryParameter par;
            foreach (var item in properties)
            {
                object value = item.GetValue(model, null);
                if (value == null) continue;
                par = new QueryParameter();
                par.OracleDbColumnName = item.Name;
                par.OracleDbColumnType = item.PropertyType == typeof(decimal) ? OracleDbType.Decimal :
                    (item.PropertyType == typeof(DateTime) ? OracleDbType.Date : OracleDbType.NVarchar2);
                par.OracleDbColumnValue = value;
                par.PredicateType = PredicateType.set;
                result.Add(par);
            }
            return result;
        }
        public static IList<QueryParameter> GenerateInsertSome<M>(M model, IList<string> exceptString)
        {
            Type type = typeof(M);
            PropertyInfo[] properties = GetPropertyInfos(type).Where(o => !exceptString.Contains(o.Name)).ToArray();
            IList<QueryParameter> result = new List<QueryParameter>();
            QueryParameter par;
            foreach (var item in properties)
            {
                object value = item.GetValue(model, null);
                if (value == null) continue;
                par = new QueryParameter();
                par.OracleDbColumnName = item.Name;
                par.OracleDbColumnType = item.PropertyType == typeof(decimal) ? OracleDbType.Decimal :
    (item.PropertyType == typeof(DateTime) ? OracleDbType.Date : OracleDbType.NVarchar2);
                par.OracleDbColumnValue = value;
                par.PredicateType = PredicateType.insert;
                result.Add(par);
            }
            return result;
        }
        public static List<M> MapperAuto<T, M>(T reader) where T : IDataReader
        {
            return Mapper.Map<T, List<M>>(reader);
        }
        private static string GetClassName(Type mType)
        {
            var keyName = "Copy_";
            keyName += mType.FullName.Replace(".", "_");
            keyName += "IDataReader";
            return keyName;
        }
        private static PropertyInfo[] GetPropertyInfos(Type mType)
        {
            string name = GetClassName(mType);
            PropertyInfo[] properties;
            lock (_maps)
            {
                if (!_maps.TryGetValue(name, out properties))
                {
                    properties = mType.GetProperties();
                    _maps.Add(name, properties);
                }
            }
            return properties;
        }
    }
}
